package com.bicntech.app.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.bicntech.common.constant.Constants;
import com.bicntech.common.constant.WXUrlConstants;
import com.bicntech.common.core.controller.AppController;
import com.bicntech.common.core.domain.R;
import com.bicntech.common.core.domain.model.LoginUser;
import com.bicntech.common.core.domain.model.QYLoginUser;
import com.bicntech.common.core.service.LogininforService;
import com.bicntech.common.enums.DeviceType;
import com.bicntech.common.enums.UserType;
import com.bicntech.common.exception.ServiceException;
import com.bicntech.common.helper.LoginHelper;
import com.bicntech.common.utils.JSON;
import com.bicntech.common.utils.MessageUtils;
import com.bicntech.common.utils.ObjectUtil;
import com.bicntech.common.utils.ServletUtils;
import com.bicntech.system.dto.WeiXinUserInfoDTO;
import com.bicntech.system.entity.UserInfo;
import com.bicntech.system.service.UserInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author jmy
 */
@Api(tags = "用户")
@Slf4j
@RestController
@RequestMapping(AppController.BASE_URI + "/user")
public class WxUserController {

    /**
     * 企业acctoken
     */
    private static String ACCESS_TOKEN = "";

    @Value("${wx.appId}")
    private String appId;

    @Value("${wx.secret}")
    private String secret;
    @Value("${wx.corpId}")
    private String corpId;

    @Value("${wx.Webpage}")
    private String Webpage;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private LogininforService asyncService;

    @GetMapping("/getLoginUrl")
    @ApiOperation(value = "获取返回code的url")
    public R<String> getLoginUrl() {
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put("corpId", corpId);
        map.put("Webpage", Webpage);
        String urlFormat = StrUtil.format(WXUrlConstants.GET_CODE, map);
        return R.ok("操作成功", urlFormat);
    }

    @GetMapping("/getUser")
    @ApiOperation(value = "获取用户token")
    public R<Map<String, Object>> getUser(@ApiParam("用户code") @NotBlank @RequestParam String code) {
        HttpServletRequest request = ServletUtils.getRequest();
        log.info("code:{} 登录", code);
        Map<String, Object> map = new HashMap<String, Object>(20);
        map.put("corpId", corpId);
        map.put("secret", secret);
        if (StrUtil.isBlank(ACCESS_TOKEN)) {
            refreshAccessToken();
        }
        log.info("access_token:{}", ACCESS_TOKEN);

        map.put("access_token", ACCESS_TOKEN);
        map.put("code", code);

        Map<String, Object> userInfoMap = getUserInfo(map);
        if (userInfoMap.get("errcode").equals(40014) || userInfoMap.get("errcode").equals(42001)) {
            log.error("access_token无效 重新刷新，code:{}，message:{}", userInfoMap.get("errcode"), userInfoMap.get("errmsg"));
            refreshAccessToken();
            map.put("access_token", ACCESS_TOKEN);
            userInfoMap = getUserInfo(map);
        }

        String userId = userInfoMap.get("UserId").toString();
        map.put("userId", userId);

        String deviceId = userInfoMap.get("DeviceId").toString();
        String mailListUrl = StrUtil.format(WXUrlConstants.MAIL_LIST, map);
        WeiXinUserInfoDTO mailListMap = JSON.toJavaObject(HttpUtil.get(mailListUrl), WeiXinUserInfoDTO.class);
        assert mailListMap != null;
        String name = mailListMap.getName();
        Integer status = mailListMap.getStatus();
        if (!mailListMap.getErrCode().equals(0)) {
            log.error("出现异常，code:{}，message:{}", mailListMap.getErrCode(), mailListMap.getErrMsg());
            throw new ServiceException("操作异常");
        }

        //同步用户信息
        UserInfo userInfo = userInfoService.getByUserId(userId);
        if (ObjectUtil.isEmptyObject(userInfo)) {
            UserInfo info = new UserInfo();
            info.setUserId(userId);
            info.setUserName(name);
            info.setUserStatus(status);
            info.setUserInfoJson(JSON.toMap(mailListMap));
            info.setCreateBy("系统");
            userInfoService.save(info);
            userInfo = info;
        }

        if (ObjectUtil.notEmpty(userInfo) &&
                !StrUtil.equals(userInfo.getUserName(), name)) {
            userInfo.setUserName(name);
            userInfo.setUserStatus(status);
            userInfo.setUserInfoJson(JSON.toMap(mailListMap));
            userInfoService.updateById(userInfo);
        }
        QYLoginUser loginUser = new QYLoginUser();
        loginUser.setQyUserId(userInfo.getUserId());
        loginUser.setUsername(userInfo.getUserName());
        loginUser.setUserId(userInfo.getId());
        loginUser.setUserType(UserType.QYWX_USER.getUserType());
        // 生成token
        LoginHelper.loginByDevice(loginUser, DeviceType.QYWX);
        asyncService.recordLogininfor(userInfo.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);

        Map<String, Object> userMap = new HashMap<>(3);
        userMap.put("token", StpUtil.getTokenValue());
        userMap.put("userName", name);
        return R.ok(userMap);
    }

    @GetMapping("/getLoginInfo")
    @ApiOperation(value = "获取当前用户信息")
    public R<LoginUser> getLoginInfo() {
        QYLoginUser loginUser = (QYLoginUser) LoginHelper.getLoginUser();
        return R.ok(loginUser);
    }


    /**
     * 刷新AccessToken
     */
    private void refreshAccessToken() {
        Map<String, Object> AccessTokenMap = new HashMap<String, Object>(10);
        AccessTokenMap.put("corpId", corpId);
        AccessTokenMap.put("Webpage", Webpage);
        AccessTokenMap.put("secret", secret);
        String accessUrl = StrUtil.format(WXUrlConstants.ACCESS_TOKEN, AccessTokenMap);
        Map<String, Object> accessTokenMap = JSON.toMap(HttpUtil.get(accessUrl));
        assert accessTokenMap != null;
        if (!accessTokenMap.get("errcode").equals(0)) {
            log.error("出现异常，code:{}，message:{}", accessTokenMap.get("errcode"), accessTokenMap.get("errmsg"));
            throw new ServiceException("操作异常");
        }
        ACCESS_TOKEN = accessTokenMap.get("access_token").toString();
    }


    private Map<String, Object> getUserInfo(Map<String, Object> map) {
        String userInfoUrl = StrUtil.format(WXUrlConstants.USER_INFO, map);
        Map<String, Object> userInfoMap = JSON.toMap(HttpUtil.get(userInfoUrl));
        assert userInfoMap != null;
        if (!userInfoMap.get("errcode").equals(0) && !userInfoMap.get("errcode").equals(40014) && !userInfoMap.get("errcode").equals(42001)) {
            log.error("出现异常，code:{}，message:{}", userInfoMap.get("errcode"), userInfoMap.get("errmsg"));
            throw new ServiceException("操作异常");
        }
        return userInfoMap;
    }


    //https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww423e6fb3bd249b32&redirect_uri=http://airport.bicntech.com:19801/doc.html&response_type=code&scope=snsapi_base&state=1000003#wechat_redirect
    //https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww423e6fb3bd249b32&redirect_uri=http://airport.bicntech.com:19801/pub/user/oauth2me.do&response_type=code&scope=snsapi_base&agentid=tiodL4YsnJ3b-H7-HUT5JvVfRcEPWkyngxgkhmVAq8c&state=https://www.baidu.com/
    //https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww423e6fb3bd249b32&redirect_uri=http://airport.bicntech.com:19801/pub/user/oauth2me.do&response_type=code&scope=snsapi_base&state=https://www.baidu.com/

    /**
     * 微信用户登录获取用户
     *
     * @param code    回调
     * @param state
     * @param request
     * @return
     * @throws IOException
     */
    @ApiIgnore
    @GetMapping("/oauth2me.do")
    @ApiOperation(value = "回调方法")
    public RedirectView getuserinfo(@RequestParam String code, @RequestParam String state, HttpServletRequest request) throws IOException {

//        System.out.println("回调方法code: " + code + "state: " + state);
//        ///BaseResult getuserinfo = weChatServicel.getuserinfo(code, request);
//        String redirectUrl = "";
//
//        if (getuserinfo.getErrno() == 200) {
//            Object o = JSONArray.toJSON(data);
//            String s = Base64Util.encryptBASE64(o.toString());
//            String encode = URLEncoder.encode(s, "UTF-8");
//            redirectUrl = state + "?" + encode;
//        } else {
//            redirectUrl = state;
//        }
//        System.out.println("重定向ＵＲＬ: " + redirectUrl);
        return new RedirectView("https://www.baidu.com/");
    }
}
